<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Generator 函数及其异步应用</title>
	</head>
	<body>
		<p>Generator 函数是 ES6 提供的一种异步编程解决方案，语法行为与传统函数完全不同</p>
		<p>Generator 函数有多种理解角度。语法上，首先可以把它理解成，Generator 函数是一个状态机，封装了多个内部状态</p>
		<p>执行 Generator 函数会返回一个遍历器对象，也就是说，Generator 函数除了状态机，还是一个遍历器对象生成函数。返回的遍历器对象，可以依次遍历 Generator 函数内部的每一个状态</p>
		<p>形式上，Generator 函数是一个普通函数，但是有两个特征。一是，function关键字与函数名之间有一个星号；二是，函数体内部使用yield表达式，定义不同的内部状态（yield在英语里的意思就是“产出”）
		</p>
		<script type="text/javascript">
			function* helloWorldGenerator() {
				yield 'hello';
				yield 'world';
				return 'ending';
			}

			var hw = helloWorldGenerator();
			console.log(hw.next()); // { value: 'hello', done: false }
			console.log(hw.next()); // { value: 'world', done: false }
			console.log(hw.next()); // { value: 'ending', done: true }
			console.log(hw.next()); // { value: undefined, done: true }

			var hw = helloWorldGenerator();
			for (let h of hw) {
				console.log(h); //'hello' 'world'
			}

			// 异步应用
			// 上面代码的函数asyncJob是一个协程，它的奥妙就在其中的yield命令。它表示执行到此处，执行权将交给其他协程。也就是说，yield命令是异步两个阶段的分界线。
			// 协程遇到yield命令就暂停，等到执行权返回，再从暂停的地方继续往后执行。它的最大优点，就是代码的写法非常像同步操作，如果去除yield命令，简直一模一样。
			function print(s) {
				console.log(s);
				return s + "-printed"
			}

			function* asyncJob() {
				// ...其他代码
				var f1 = yield print("async1");
				var f2 = yield print("async2");
				var f3 = yield print("async3");
				// ...其他代码
			}

			let asyncJobs = asyncJob();
			// asyncJobs.next(); //async1
			// asyncJobs.next(); //async2
			// asyncJobs.next(); //async3
			for (let a of asyncJob()); // async1 async2 async3
		</script>
	</body>
</html>
